{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.4"
    },
    "pycharm": {
      "stem_cell": {
        "cell_type": "raw",
        "metadata": {
          "collapsed": false
        },
        "source": []
      }
    },
    "colab": {
      "name": "python_r_basics.ipynb",
      "provenance": []
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "77k8D7YFv-7I"
      },
      "source": [
        "# Python/R Basics\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LkPBDMvmv-7N"
      },
      "source": [
        "## Python Basics\n",
        " \n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kt4ffPp4v-7N"
      },
      "source": [
        "### Define Functions"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qmWEkneFwys2"
      },
      "source": [
        "Note that type hint will not force type conversion (unlike cython or other statically typed language)."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "TGZR3d2Jv-7O"
      },
      "source": [
        "def myfunc(a:float, *args, **kwargs) -> str:\n",
        "    return str(a)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "id": "CIyyLTc1v-7O",
        "outputId": "5e909977-2c04-4eea-c6a3-591b148169c2"
      },
      "source": [
        "# This should not work, but it DOES!\n",
        "import numpy as np\n",
        "x = np.array([1,1])\n",
        "myfunc(x)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            },
            "text/plain": [
              "'[1 1]'"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 2
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "w0V12K5VwxU1"
      },
      "source": [
        "`*args` is called list unpacks. Inside the function, the `args` are just like lists. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "c_yfxCOGv-7O",
        "outputId": "25bb35a2-20e3-4cce-ad40-c0269f4c15fe"
      },
      "source": [
        "def mysum(*args):\n",
        "    result = 0\n",
        "    for x in args:\n",
        "        result += x\n",
        "    return result\n",
        "mysum(1,2,3) # Works\n",
        "mysum(2,3,5,6) #Works"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "16"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 4
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4Qt9sVxnxUVv"
      },
      "source": [
        "On the other hand, `**kwargs` is called keyword argument. It is basically a python dictionary. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "6s-dM0bxyAzd",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 321
        },
        "outputId": "1cd7b566-edb7-4156-d27a-bbd6d26445e7"
      },
      "source": [
        "def my_concat(**kwargs):\n",
        "    result = \"\"\n",
        "    \n",
        "    for k, v in kwargs.items():\n",
        "        result += v\n",
        "    return result\n",
        "my_concat(x=\"a\",y=\"b\") # works\n",
        "my_concat(fff = 1, bsr=2) # not really"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "error",
          "ename": "TypeError",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-5-d4dc5b842b05>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      6\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0mmy_concat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"a\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"b\"\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# works\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0mmy_concat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfff\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbsr\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# works\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;32m<ipython-input-5-d4dc5b842b05>\u001b[0m in \u001b[0;36mmy_concat\u001b[0;34m(**kwargs)\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m     \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m         \u001b[0mresult\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      6\u001b[0m     \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0mmy_concat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"a\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0my\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m\"b\"\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# works\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;31mTypeError\u001b[0m: must be str, not int"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ThdvxhGYv-7P"
      },
      "source": [
        "### Exception Handling\n",
        "\n",
        "---\n",
        "The most commonly used ways for exception handling is to raise an exception (also called throw). "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "yL8uNyM0v-7P"
      },
      "source": [
        "def raise_exception(x):\n",
        "    raise Exception(\"I am an EXCEPTION!!!\") # Something bad has happend\n",
        "\n",
        "def catcher(x):\n",
        "    try:\n",
        "        raise_exception(x) # This will run the code. If everything is fine, it will return normally.\n",
        "    except (TypeError, NameError):  # If a specific error occurs, this will follow the behavior. \n",
        "        print(\"I am ok with this!\")\n",
        "    except Exception as e: # This is often used to handle unknown exception, by letting someone else do the job\n",
        "        raise e\n",
        "    finally: # This will always execute no matter what\n",
        "        print(\"Let us swallow everything when exception occurs!\")\n",
        "    \n",
        "    "
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "8h2DbzdGv-7P",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 328
        },
        "outputId": "bbe7b8a1-cbd3-4b14-8e2d-850466862da9"
      },
      "source": [
        "catcher(1)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Let us swallow everything when exception occurs!\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "error",
          "ename": "Exception",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mException\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-7-187b7f8ca604>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mcatcher\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;32m<ipython-input-6-4c0de9df19b7>\u001b[0m in \u001b[0;36mcatcher\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m      8\u001b[0m         \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"I am ok with this!\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      9\u001b[0m     \u001b[0;32mexcept\u001b[0m \u001b[0mException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# This is often used to handle unknown exception, by letting someone else do the job\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m         \u001b[0;32mraise\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m     11\u001b[0m     \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# This will always execute no matter what\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m     12\u001b[0m         \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Let us swallow everything when exception occurs!\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m<ipython-input-6-4c0de9df19b7>\u001b[0m in \u001b[0;36mcatcher\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcatcher\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 6\u001b[0;31m         \u001b[0mraise_exception\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# This will run the code. If everything is fine, it will return normally.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      7\u001b[0m     \u001b[0;32mexcept\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mTypeError\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mNameError\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m  \u001b[0;31m# If a specific error occurs, this will follow the behavior.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      8\u001b[0m         \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"I am ok with this!\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;32m<ipython-input-6-4c0de9df19b7>\u001b[0m in \u001b[0;36mraise_exception\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mraise_exception\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m     \u001b[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"I am an EXCEPTION!!!\"\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# Something bad has happend\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mcatcher\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      5\u001b[0m     \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
            "\u001b[0;31mException\u001b[0m: I am an EXCEPTION!!!"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "d_jAkz7OzNB1"
      },
      "source": [
        "There are quite some problem with the following approach.\n",
        "\n",
        "\n",
        "\n",
        "*   It breaks the program, as long as one exception is not handled.\n",
        "*   This is ok if we are testing our code. However, if this is a production system, you don't want a night time call to restart the system.\n",
        "*   Once one function throws an exception, everyone else that calls the function has to modify their code by addding `try-except` blocks.\n",
        "*   Many exception will be passed all the way to the top, and then handled. However, the top function does not know the details of each function! Therefore, it is extremely hard to devise a complete plan. \n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "w4_WUu9Cz2RL"
      },
      "source": [
        "An alternative way is to use log. There are many logging options and we will not delve into the details. The idiom is to log what goes wrong and specify the bevahior. \n",
        "\n",
        "The advantage is that you will keep the program warning, and by adjusting the log level, you can adjust the behavior. However, **someone still have to handle the exceptions!**"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "9QV8D7Knv-7Q",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "dcd3b385-faa1-4377-e2bd-6bede7490771"
      },
      "source": [
        "import logging\n",
        "logging.info(\"This is some useful information.\")\n",
        "logging.warning(\"This is some warning!\")\n",
        "logging.error(\"Something went wrong!\")\n"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "WARNING:root:This is some warning!\n",
            "ERROR:root:Something went wrong!\n"
          ],
          "name": "stderr"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "7_nazaSC0ds2"
      },
      "source": [
        "A final option, that is very popular is to use a Monad. Monad is quite complex to explain. So let us see an example. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zEzDul9T1AnU"
      },
      "source": [
        "class Failure():\n",
        "    def __init__(self, value, failed=False):\n",
        "        self.value = value\n",
        "        self.failed = failed\n",
        "    def get(self):\n",
        "        return self.value\n",
        "    def is_failed(self):\n",
        "        return self.failed\n",
        "    def __str__(self):\n",
        "        return ' '.join([str(self.value), str(self.failed)])\n",
        "    def __or__(self, f):\n",
        "        if self.failed:\n",
        "            return self\n",
        "        try:\n",
        "            x = f(self.get())\n",
        "            return Failure(x)\n",
        "        except:\n",
        "            return Failure(None, True)"
      ],
      "execution_count": 101,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "GV3tlwTH1EzP",
        "outputId": "400b3d84-98b1-46eb-d9d7-59429d8d49d0"
      },
      "source": [
        "# This will work.\n",
        "from operator import neg\n",
        "x = '1'\n",
        "y = Failure(x) | int | neg | str\n",
        "print(y)"
      ],
      "execution_count": 102,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "-1 False\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "PIKc2eru16ps",
        "outputId": "5c471d10-eef7-4d6f-8ae2-ec607b037aab"
      },
      "source": [
        "# This will not\n",
        "from operator import neg\n",
        "x = 'hahaha'\n",
        "y = Failure(x) | int | neg | str\n",
        "print(y)"
      ],
      "execution_count": 103,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "None True\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CwDDrPQ62jn-"
      },
      "source": [
        "A beautiful collection of functional programming primitives can be found [here](https://github.com/jasondelaat/pymonad.git). Use the following command to install.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "f-qRTXp3v-7Q"
      },
      "source": [
        "### Python Class"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "WMIqTOnkv-7Q"
      },
      "source": [
        "class MyClass(object):\n",
        "    def __init__(self, x):\n",
        "        self.x = x\n",
        "    def __del__(self): # WARNING: Perhaps a very bad idea!\n",
        "        print(\"I am gone\")"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "HFxU9U2Nv-7Q"
      },
      "source": [
        "my_class = MyClass(1)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "oKH1m7ZQv-7Q",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "694334ef-ca16-40ba-a8a3-2fc0c1911089"
      },
      "source": [
        "del my_class"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "I am gone\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "ZOCTWQQ9v-7R",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 168
        },
        "outputId": "e0946f3e-b2b8-4129-e063-eea33b3effb1"
      },
      "source": [
        "my_class"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "error",
          "ename": "NameError",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-15-3528c0db2c60>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmy_class\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;31mNameError\u001b[0m: name 'my_class' is not defined"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "hU941s5-v-7R"
      },
      "source": [
        "my_class_a = MyClass(1)\n",
        "my_class_b = my_class_a\n",
        "my_class_c = MyClass(1)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "iNFfKBexv-7R",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "8f15455d-041d-4acc-bc84-22d57e74c13c"
      },
      "source": [
        "my_class_b.x= 2\n",
        "print(my_class_a.x) # Note that this is a reference to the class, therefore, they are pointing to the same thing which is why it changes. "
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "2\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "tZ0iYfeBv-7R",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "72e4912f-6a24-4a44-bf8f-265d06e5205d"
      },
      "source": [
        "my_class_b == my_class_a"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 18
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "v4y3z3ptv-7R",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "7d8a96b4-01df-4f1c-a025-2cbb847d343e"
      },
      "source": [
        "my_class_a = MyClass(1)\n",
        "my_class_c = MyClass(1)\n",
        "my_class_a == my_class_c"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "I am gone\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "False"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 19
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "NsYH2c7rv-7R",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "2ffa2acf-c02e-43b3-cee4-d175f515a02e"
      },
      "source": [
        "from copy import deepcopy\n",
        "my_class_a = MyClass(1)\n",
        "my_class_b = deepcopy(my_class_a)\n",
        "my_class_b == my_class_a"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "I am gone\n",
            "I am gone\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "False"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 20
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "16O41n_-v-7R",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "5728ce1b-9112-43c2-f8f7-1a1c615211ef"
      },
      "source": [
        "my_class_b.x= 2\n",
        "print(my_class_a.x)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Owm0io_7v-7S"
      },
      "source": [
        "### The Ghost Bus Incidence\n",
        "\n",
        "---\n",
        "Is it usually a terrible idea to use mutable variables as default argument. The following snippets illustrate the point. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "hWcygEKFv-7S"
      },
      "source": [
        "class GhostBus:\n",
        "    def __init__(self, passengers=[]):\n",
        "        self.passengers = passengers\n",
        "    \n",
        "    def pick(self, name):\n",
        "        self.passengers.append(name)\n",
        "        \n",
        "    def drop(self, name):\n",
        "        self.passengers.remove(name)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "-9cjnum2v-7S",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "b6d6c4e8-5dee-43ff-f2b1-08151b1fc876"
      },
      "source": [
        "# Run this several times\n",
        "ghost_bus = GhostBus()\n",
        "ghost_bus.pick('A Ghost')\n",
        "ghost_bus.passengers"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "['A Ghost']"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 23
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "YW2Mmym6x_OG"
      },
      "source": [
        "What goes wrong here? Note that self.passengers is a reference to passengers, and passengers is a refernece to `[]` (which is global). Note when you mutate self.passengers, you are mutating `[]` as well. So please use `None` instead. "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LdMnbYxDv-7S"
      },
      "source": [
        "### Common Data Structures: List\n",
        "\n",
        "---\n",
        "Python list is a little bit like C++ vector, except it can hold any type of object. It is ordered. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "u37CChEXv-7S"
      },
      "source": [
        "a = []\n",
        "# a = list()\n",
        "b= [1,a,'2']"
      ],
      "execution_count": 104,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "_j42XYXZzV-r",
        "outputId": "da97aeca-46b6-40db-c10a-762e822d8f36"
      },
      "source": [
        "b"
      ],
      "execution_count": 105,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[1, [], '2']"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 105
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "6eUkPbSVv-7S",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "9f2df282-7706-417c-8196-9233748ece7e"
      },
      "source": [
        "b[0]"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "1"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 39
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "NTPUDvEhv-7T",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "29d426df-605d-4e42-f6b2-fd614cadad91"
      },
      "source": [
        "b[:1]"
      ],
      "execution_count": 106,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[1]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 106
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "F9z2pMDnv-7T",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "a783e2c3-6963-4b37-babe-c9e969befcdd"
      },
      "source": [
        "b[1:]"
      ],
      "execution_count": 107,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[[], '2']"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 107
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "MtL9tBILv-7T",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "410688e8-e2f2-4829-ce3f-f85ea05c4627"
      },
      "source": [
        "b[2:3]"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "['2']"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 42
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "aswePQjav-7T",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 35
        },
        "outputId": "e20ce8f0-f824-4fcf-c986-b3e1f5cce928"
      },
      "source": [
        "b[-1]"
      ],
      "execution_count": 108,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "application/vnd.google.colaboratory.intrinsic+json": {
              "type": "string"
            },
            "text/plain": [
              "'2'"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 108
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "uJGc1GChv-7T",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "82be4b9a-8630-4ffa-a4b9-fdbb6763e6c0"
      },
      "source": [
        "b[:-2]"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[1]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 44
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "nVgXgPopv-7T",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "80607853-995f-4e5b-cd15-eb1eaf122f56"
      },
      "source": [
        "b.append(5)\n",
        "b"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[1, [], '2', 5]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 45
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "yQGXGx53v-7T",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "88ef476b-8d3e-409d-c861-d5b4b63c350e"
      },
      "source": [
        "b.extend([1,2])\n",
        "b"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[1, [], '2', 5, 1, 2]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 46
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "_Kw4x2YTv-7T",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "2dbfe83d-53d1-42a3-e77a-94fef2fd1add"
      },
      "source": [
        "b.insert(1,'haha')\n",
        "b"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[1, 'haha', [], '2', 5, 1, 2]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 47
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "BtQTt2Knv-7U",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "eec674dc-1297-4276-a68a-207fced6d30a"
      },
      "source": [
        "del b[0]\n",
        "b"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "['haha', [], '2', 5, 1, 2]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 48
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "mtJbHA2xv-7U"
      },
      "source": [
        "b.remove(1)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "l8z0rKlAv-7U",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "72358cc3-574c-4873-d600-c3efe241bbe8"
      },
      "source": [
        "matrix  = [[1,2],[3,4],[5,6],[7,8]]\n",
        "matrix"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "[[1, 2], [3, 4], [5, 6], [7, 8]]"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 50
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "bo0C4l_Gv-7U"
      },
      "source": [
        "tranpose =[[row[i] for row in matrix] for i in range(2)]"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Wt67-b6R354P"
      },
      "source": [
        "To understand what happens. Note that we have used a syntax. In short.\n",
        "\n",
        "```\n",
        "x = [i*2 for i in range(10]\n",
        "```\n",
        "\n",
        "is the same as\n",
        "\n",
        "```\n",
        "x = list()\n",
        "for i in range(10):\n",
        "    x.append(i*2)\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "5c537gAjv-7U"
      },
      "source": [
        "### Common Data Structures: Set\n",
        "\n",
        "---\n",
        "This is essentially a hashset, basically means it is unordered. The 'equivalent' in C++ will be unordered_set. Also, there are no duplicate element. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "Nk9-pzwov-7U"
      },
      "source": [
        "a = {1,2,3}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "i-OYhqe3v-7V",
        "outputId": "4b4f0bb1-a379-42d5-863b-d6f69cc6c331"
      },
      "source": [
        "my_set = {1, 3}\n",
        "print(my_set)\n",
        "my_set.add(2)\n",
        "print(my_set)\n",
        "my_set.update([2, 3, 4])\n",
        "print(my_set)\n",
        "my_set.update([4, 5], {1, 6, 8})\n",
        "print(my_set)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{1, 3}\n",
            "{1, 2, 3}\n",
            "{1, 2, 3, 4}\n",
            "{1, 2, 3, 4, 5, 6, 8}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "a3sa7o0iv-7V",
        "outputId": "246259a8-37c9-4d7b-8f3c-fcfe558ae458"
      },
      "source": [
        "my_set.add(1)\n",
        "my_set"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{1, 2, 3, 4, 5, 6, 8}"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 62
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "_J4Owc8gv-7V",
        "outputId": "ae4d3dd8-c48f-488e-f634-1cf134246b9c"
      },
      "source": [
        "my_set.remove(1)\n",
        "my_set"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{2, 3, 4, 5, 6, 8}"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 63
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "WDGuisgxv-7V"
      },
      "source": [
        "set_a = {1,2,3}\n",
        "set_b = {3,4,5}"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bfhNGkEC4fo6"
      },
      "source": [
        "Here are some set operations. Pretty self-explanatory. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ROcO-nu3v-7V",
        "outputId": "a6951f34-16ea-438a-b453-16efaf04c214"
      },
      "source": [
        "print(set_a|set_b)\n",
        "print(set_a - set_b)\n",
        "print(set_b - set_a)\n",
        "print(set_a.union(set_b))\n",
        "print(set_a.intersection(set_b))\n",
        "print(set_a^set_b)"
      ],
      "execution_count": 109,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{1, 2, 3, 4, 5}\n",
            "{1, 2}\n",
            "{4, 5}\n",
            "{1, 2, 3, 4, 5}\n",
            "{3}\n",
            "{1, 2, 4, 5}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "PNvXypsIv-7V"
      },
      "source": [
        "### Common Data Structures: Dict\n",
        "\n",
        "---\n",
        "Dict is basically a hashmap. Its 'equivalent' in C++ will be unordered map. Therefore it is not with an order. To avoid pain, if you need order, use OrderedDict. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "SP6bu2giv-7V"
      },
      "source": [
        "a = dict()\n",
        "a = {'x':'1', 'y':'2'}"
      ],
      "execution_count": 110,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "Dy29kC3Dv-7W",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 202
        },
        "outputId": "7e05fac8-0617-4fc7-df03-d679fb523ee4"
      },
      "source": [
        "print(a['x'])\n",
        "print(a['not_here'])"
      ],
      "execution_count": 111,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "1\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "error",
          "ename": "KeyError",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mKeyError\u001b[0m                                  Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-111-53b2d82448a8>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'x'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'not_here'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;31mKeyError\u001b[0m: 'not_here'"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "q7ez_5SUv-7W",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "c0b38b47-4576-42e0-af08-24a0530be51e"
      },
      "source": [
        "a['new_element'] = 'haha'\n",
        "print(a)"
      ],
      "execution_count": 112,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{'x': '1', 'y': '2', 'new_element': 'haha'}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "g1rNJr8Zv-7W"
      },
      "source": [
        "print(a.keys())\n",
        "print(a.values())"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "k1scCz2Fv-7W"
      },
      "source": [
        "del a['new_element']"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "oa5nS6_Uv-7W"
      },
      "source": [
        "a"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "z0g1Wtnbv-7W",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "6f8cbc5a-cd7c-4fe9-d718-f7e39a011f26"
      },
      "source": [
        "keys = ['a','b','c']\n",
        "values = [1,2,3]\n",
        "dict_from_zip = dict(zip(keys, values))\n",
        "print(dict_from_zip)"
      ],
      "execution_count": 113,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{'a': 1, 'b': 2, 'c': 3}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "8OQ1ud3zv-7W"
      },
      "source": [
        "def my_concat(**kwargs):\n",
        "    result = \"\"\n",
        "    \n",
        "    for k, v in kwargs.items():\n",
        "        result += v\n",
        "    return result\n",
        "my_concat(x=\"a\",y=\"b\")"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "tjCvA7jOv-7W",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 168
        },
        "outputId": "02932507-41d7-42a4-88f8-33ed39c7bff8"
      },
      "source": [
        "my_concat(**a)"
      ],
      "execution_count": 115,
      "outputs": [
        {
          "output_type": "error",
          "ename": "TypeError",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-115-cd792e88b9db>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mmy_concat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;31mTypeError\u001b[0m: my_concat() takes 0 positional arguments but 1 was given"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "FBSlkjtCv-7X",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "dacb73a5-83b3-433c-9ac4-323a489a6404"
      },
      "source": [
        "# You can also use dict comprehension to shorten your code. \n",
        "odd_squares = {x: x*x for x in range(11) if x % 2 == 1}\n",
        "print(odd_squares)"
      ],
      "execution_count": 114,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "{1: 1, 3: 9, 5: 25, 7: 49, 9: 81}\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Ef5oeStkv-7X"
      },
      "source": [
        "### Common Data Structure: NamedTuple"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "UH691fCTv-7X"
      },
      "source": [
        "from collections import namedtuple"
      ],
      "execution_count": 116,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "PV9Byp-0v-7X"
      },
      "source": [
        "employee = namedtuple('Employee', ['age','place', 'education'])"
      ],
      "execution_count": 117,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "LVhPg5jMv-7X"
      },
      "source": [
        "tom = employee(age=10, place='beijing', education='none')"
      ],
      "execution_count": 118,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "rJAuWy5Qv-7X",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "0f426200-1d94-4808-824e-1ab8e7b9825c"
      },
      "source": [
        "print(tom)"
      ],
      "execution_count": 119,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Employee(age=10, place='beijing', education='none')\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "2BTBwzILv-7X"
      },
      "source": [
        "### Common Data Structure: dataclass\n",
        "\n",
        "---\n",
        "\n",
        "Data class is a great way to pass many parameters to a function. It helps with documentation, with range check, so people won't just stack anything into it. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "zVrtZQvmv-7Y"
      },
      "source": [
        "from dataclasses import dataclass, field\n",
        "from typing import Optional"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "vcmPfkifv-7Y"
      },
      "source": [
        "@dataclass\n",
        "class MyDataClass:\n",
        "    name : str = field(\n",
        "    default='tom',\n",
        "    metadata={'help':\"Name of the person\"})\n",
        "    \n",
        "    age: Optional[int] = field(\n",
        "    default = None,\n",
        "    metadata={'help':\"Age of the pesson. Optional.\"})\n",
        "    \n",
        "    vip: int = field(\n",
        "    default = 100,\n",
        "    metadata = {'help':\"Some very important field.\"})\n",
        "        \n",
        "\n",
        "    def __post_init__(self): # This function will help you to handle illegal argument. \n",
        "        if self.vip <= 0:\n",
        "            raise Exception(\"That important thing has to be larger than 0\")\n",
        "            \n",
        "    @property\n",
        "    def age_type(self):\n",
        "        if self.age >= 100:\n",
        "            return 'You are old'\n",
        "        else:\n",
        "            return 'You are still young' "
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "KoU5uzokv-7Y",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "498b8202-78eb-40ac-a5cd-3e7cbb1b7629"
      },
      "source": [
        "my_data_class = MyDataClass(name='jerry', age = 20)\n",
        "print(my_data_class)"
      ],
      "execution_count": 121,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "MyDataClass(name='jerry', age=20, vip=100)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "QFmmyKNTv-7Y",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "8ed4c83c-a89d-41ac-cc84-c798ae461ffb"
      },
      "source": [
        "print(my_data_class.age)\n",
        "print(my_data_class.age_type)\n"
      ],
      "execution_count": 122,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "20\n",
            "You are still young\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "BK-Yiafq5peu"
      },
      "source": [
        "A word about docs. \n",
        "\n",
        "In general, using [Spinx](https://www.sphinx-doc.org/en/master/) to generate a documentaion is a pretty good idea. Therefore, some command should be given to functions. In general, for public api's, the docstring should include at least \n",
        "\n",
        "1.   Functionality\n",
        "2.   Argument type and explanation.\n",
        "3.   Return type.\n",
        "4.   (Optional) A use case. \n",
        "\n",
        "Note that if a function will change some of the input parameter. This **MUST** be highlighted in the doc. \n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_FD3zhmz6ZNo"
      },
      "source": [
        "## R \n",
        "\n",
        "---\n",
        "Before we venture into more advanced staff. Let us introduce very briefly what R does, and magic functions. To use R, you have to activate the functionality. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "rhr6T4n46jd6",
        "outputId": "a0eb6c09-18f0-4473-c37b-0666cd1545d1"
      },
      "source": [
        "%load_ext rpy2.ipython"
      ],
      "execution_count": 123,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "The rpy2.ipython extension is already loaded. To reload it, use:\n",
            "  %reload_ext rpy2.ipython\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "au4UQkCe61qZ"
      },
      "source": [
        "To use R, we can use `%%R` cell magic. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "8M1R_P-U6zgP",
        "outputId": "47d41b60-f2d8-471c-cf22-f0b53675dd00"
      },
      "source": [
        "%%R # \bThis means \n",
        "install.packages('dplyr')"
      ],
      "execution_count": 124,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "NULL\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "MdsRApIH9qQQ",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "09d0fd46-3033-4951-8a58-43da9e4247a2"
      },
      "source": [
        "%%R \n",
        "library('caret')"
      ],
      "execution_count": 125,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "WARNING:rpy2.rinterface_lib.callbacks:R[write to console]: Error in library(\"caret\") : there is no package called ‘caret’\n",
            "Calls: <Anonymous> -> <Anonymous> -> withVisible -> library\n",
            "\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "\n",
            "Error in library(\"caret\") : there is no package called ‘caret’\n",
            "Calls: <Anonymous> -> <Anonymous> -> withVisible -> library\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "d3Dx5y749t4a",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "ebecedcc-8fb5-4bf7-bc3a-c732a0044a66"
      },
      "source": [
        "%%R\n",
        "a <- 1\n",
        "2 -> b\n",
        "c = 1\n",
        "a == c"
      ],
      "execution_count": 126,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[1] TRUE\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "1Atuc2Cm-Gqa",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "f76f80e8-17c9-4ae0-c0a6-b13486fbac38"
      },
      "source": [
        "%%R\n",
        "for (i in 1:100){\n",
        "    print(i)\n",
        "}"
      ],
      "execution_count": 127,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[1] 1\n",
            "[1] 2\n",
            "[1] 3\n",
            "[1] 4\n",
            "[1] 5\n",
            "[1] 6\n",
            "[1] 7\n",
            "[1] 8\n",
            "[1] 9\n",
            "[1] 10\n",
            "[1] 11\n",
            "[1] 12\n",
            "[1] 13\n",
            "[1] 14\n",
            "[1] 15\n",
            "[1] 16\n",
            "[1] 17\n",
            "[1] 18\n",
            "[1] 19\n",
            "[1] 20\n",
            "[1] 21\n",
            "[1] 22\n",
            "[1] 23\n",
            "[1] 24\n",
            "[1] 25\n",
            "[1] 26\n",
            "[1] 27\n",
            "[1] 28\n",
            "[1] 29\n",
            "[1] 30\n",
            "[1] 31\n",
            "[1] 32\n",
            "[1] 33\n",
            "[1] 34\n",
            "[1] 35\n",
            "[1] 36\n",
            "[1] 37\n",
            "[1] 38\n",
            "[1] 39\n",
            "[1] 40\n",
            "[1] 41\n",
            "[1] 42\n",
            "[1] 43\n",
            "[1] 44\n",
            "[1] 45\n",
            "[1] 46\n",
            "[1] 47\n",
            "[1] 48\n",
            "[1] 49\n",
            "[1] 50\n",
            "[1] 51\n",
            "[1] 52\n",
            "[1] 53\n",
            "[1] 54\n",
            "[1] 55\n",
            "[1] 56\n",
            "[1] 57\n",
            "[1] 58\n",
            "[1] 59\n",
            "[1] 60\n",
            "[1] 61\n",
            "[1] 62\n",
            "[1] 63\n",
            "[1] 64\n",
            "[1] 65\n",
            "[1] 66\n",
            "[1] 67\n",
            "[1] 68\n",
            "[1] 69\n",
            "[1] 70\n",
            "[1] 71\n",
            "[1] 72\n",
            "[1] 73\n",
            "[1] 74\n",
            "[1] 75\n",
            "[1] 76\n",
            "[1] 77\n",
            "[1] 78\n",
            "[1] 79\n",
            "[1] 80\n",
            "[1] 81\n",
            "[1] 82\n",
            "[1] 83\n",
            "[1] 84\n",
            "[1] 85\n",
            "[1] 86\n",
            "[1] 87\n",
            "[1] 88\n",
            "[1] 89\n",
            "[1] 90\n",
            "[1] 91\n",
            "[1] 92\n",
            "[1] 93\n",
            "[1] 94\n",
            "[1] 95\n",
            "[1] 96\n",
            "[1] 97\n",
            "[1] 98\n",
            "[1] 99\n",
            "[1] 100\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zopVUBV0-YQv"
      },
      "source": [
        "%%R\n",
        "myfunc <- function(a){\n",
        "    a = a+1\n",
        "    return(a+1)\n",
        "}"
      ],
      "execution_count": 128,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "t5hDC1th-g7B",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "b35d988e-a25a-43cb-f095-1494edcb0429"
      },
      "source": [
        "%%R\n",
        "myfunc(a) # It will usually make a copy"
      ],
      "execution_count": 129,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[1] 3\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "WmpzpUsv-sZR",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "042a57c8-03af-4226-f190-2940d0a0969a"
      },
      "source": [
        "%%R\n",
        "a"
      ],
      "execution_count": 130,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "[1] 1\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "AEgFtkuN-vOt"
      },
      "source": [
        "%%R\n",
        "data(mtcars) # This is a built-in R dataset"
      ],
      "execution_count": 131,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "tdteFBmp-0sm",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "38422bde-20f2-4a71-ef5f-ac89801611f8"
      },
      "source": [
        "%%R\n",
        "summary(mtcars)"
      ],
      "execution_count": 132,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "      mpg             cyl             disp             hp       \n",
            " Min.   :10.40   Min.   :4.000   Min.   : 71.1   Min.   : 52.0  \n",
            " 1st Qu.:15.43   1st Qu.:4.000   1st Qu.:120.8   1st Qu.: 96.5  \n",
            " Median :19.20   Median :6.000   Median :196.3   Median :123.0  \n",
            " Mean   :20.09   Mean   :6.188   Mean   :230.7   Mean   :146.7  \n",
            " 3rd Qu.:22.80   3rd Qu.:8.000   3rd Qu.:326.0   3rd Qu.:180.0  \n",
            " Max.   :33.90   Max.   :8.000   Max.   :472.0   Max.   :335.0  \n",
            "      drat             wt             qsec             vs        \n",
            " Min.   :2.760   Min.   :1.513   Min.   :14.50   Min.   :0.0000  \n",
            " 1st Qu.:3.080   1st Qu.:2.581   1st Qu.:16.89   1st Qu.:0.0000  \n",
            " Median :3.695   Median :3.325   Median :17.71   Median :0.0000  \n",
            " Mean   :3.597   Mean   :3.217   Mean   :17.85   Mean   :0.4375  \n",
            " 3rd Qu.:3.920   3rd Qu.:3.610   3rd Qu.:18.90   3rd Qu.:1.0000  \n",
            " Max.   :4.930   Max.   :5.424   Max.   :22.90   Max.   :1.0000  \n",
            "       am              gear            carb      \n",
            " Min.   :0.0000   Min.   :3.000   Min.   :1.000  \n",
            " 1st Qu.:0.0000   1st Qu.:3.000   1st Qu.:2.000  \n",
            " Median :0.0000   Median :4.000   Median :2.000  \n",
            " Mean   :0.4062   Mean   :3.688   Mean   :2.812  \n",
            " 3rd Qu.:1.0000   3rd Qu.:4.000   3rd Qu.:4.000  \n",
            " Max.   :1.0000   Max.   :5.000   Max.   :8.000  \n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "kwkdxgZ9-4ft",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "836ed8ea-b6fd-49ba-ad82-0ecbcf902279"
      },
      "source": [
        "%%R\n",
        "mtcars$mpg"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            " [1] 21.0 21.0 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 17.8 16.4 17.3 15.2 10.4\n",
            "[16] 10.4 14.7 32.4 30.4 33.9 21.5 15.5 15.2 13.3 19.2 27.3 26.0 30.4 15.8 19.7\n",
            "[31] 15.0 21.4\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "QTD17FDxv-7Y"
      },
      "source": [
        "# Magic Functions in Python Object\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "YdKoD7fav-7Y"
      },
      "source": [
        "class Vector:\n",
        "    def __init__(self, x=0, y=0):\n",
        "        self.x = x\n",
        "        self.y = y"
      ],
      "execution_count": 136,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LTsFViqUv-7Y"
      },
      "source": [
        "Let us see if we can print it out in a nice way. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "EnNxTCV5v-7Y"
      },
      "source": [
        "class Vector:\n",
        "    def __init__(self, x=0, y=0):\n",
        "        self.x = x\n",
        "        self.y = y\n",
        "\n",
        "    def __repr__(self):\n",
        "        return 'Vector(%r,%r)' % (self.x, self.y)\n",
        "    def __str__(self):                              \n",
        "        return 'Vector(%r,%r)' % (self.x, self.y)"
      ],
      "execution_count": 138,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "9JyjIDbVv-7Z",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "8d11684f-85f1-43d0-8eb3-d6a5b30d0959"
      },
      "source": [
        "v = Vector(1,2)\n",
        "print(str(v))\n",
        "print(v)"
      ],
      "execution_count": 139,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Vector(1,2)\n",
            "Vector(1,2)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "urebnixrv-7Z"
      },
      "source": [
        "How about some arithmatics?"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "_ayvAl-uv-7Z"
      },
      "source": [
        "class Vector:\n",
        "    def __init__(self, x=0, y=0):\n",
        "        self.x = x\n",
        "        self.y = y\n",
        "\n",
        "    def __repr__(self):\n",
        "        return 'Vector(%r,%r)' % (self.x, self.y)\n",
        "    \n",
        "    def __add__(self, other):\n",
        "        x = self.x + other.x\n",
        "        y = self.y + other.y\n",
        "        return Vector(x, y)\n",
        "    \n",
        "    def __sub__(self, other):\n",
        "        x = self.x - other.x\n",
        "        y = self.y - other.y\n",
        "        return Vector(x, y)\n",
        "    \n",
        "    def __mul__(self, scalar):\n",
        "        return Vector(self.x * scalar, self.y * scalar)"
      ],
      "execution_count": 141,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "RoeslxP-v-7Z"
      },
      "source": [
        "v1 = Vector(0,0)\n",
        "v2 = Vector(1,2)\n",
        "\n",
        "v1 *= 2"
      ],
      "execution_count": 145,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kn5neGbjv-7Z"
      },
      "source": [
        "How about comparison"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "HUbPuHaiv-7Z"
      },
      "source": [
        "from math import hypot\n",
        "\n",
        "class Vector:\n",
        "    def __init__(self, x=0, y=0):\n",
        "        self.x = x\n",
        "        self.y = y\n",
        "\n",
        "    def __repr__(self):\n",
        "        return 'Vector(%r,%r)' % (self.x, self.y)\n",
        "    \n",
        "    def __add__(self, other):\n",
        "        x = self.x + other.x\n",
        "        y = self.y + other.y\n",
        "        return Vector(x, y)\n",
        "    \n",
        "    def __sub__(self, other):\n",
        "        x = self.x - other.x\n",
        "        y = self.y - other.y\n",
        "        return Vector(x, y)\n",
        "    \n",
        "    def __mul__(self, scalar):\n",
        "        return Vector(self.x * scalar, self.y * scalar)\n",
        "    \n",
        "    def __abs__(self):\n",
        "        return hypot(self.x, self.y)\n",
        "    \n",
        "    def __bool__(self):\n",
        "        return bool(abs(self))\n",
        "    \n",
        "    def __eq__(self, other):\n",
        "        return self.x == other.x and self.y == other.y\n",
        "    \n",
        "    def __lt__(self, other):\n",
        "        return abs(self) < abs(other)\n",
        "    \n",
        "    def __gt__(self, other):\n",
        "        return abs(self) > abs(other)"
      ],
      "execution_count": 147,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "lmK0Dk3Ov-7a",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "48d72ea4-5e36-47f6-8f7d-795d607fdd54"
      },
      "source": [
        "v1 = Vector(1,1)\n",
        "v2 = Vector(1,1)\n",
        "v3 = Vector(1,2)\n",
        "\n",
        "print(v1 == v2)\n",
        "print(v1 == v3)\n",
        "\n",
        "print(v3 > v1)\n",
        "print(v1 < v3)"
      ],
      "execution_count": 148,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "True\n",
            "False\n",
            "True\n",
            "True\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "k9hGcr9Bv-7a"
      },
      "source": [
        "## Basic Functional Programming in Python"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "V4dBSftjv-7b"
      },
      "source": [
        "### Common Higher Order Function"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "A8-9geUfv-7b",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "d1dca22c-cf75-4757-e430-e61c417b2656"
      },
      "source": [
        "my_input = [1,2,3,4,5,6,6]\n",
        "result = map(lambda x: x+1, my_input)\n",
        "print(result) # map is lazy\n",
        "print(list(result))"
      ],
      "execution_count": 149,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "<map object at 0x7f671554e2b0>\n",
            "[2, 3, 4, 5, 6, 7, 7]\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "sJcV-c8Vv-7b"
      },
      "source": [
        "from functools import reduce\n",
        "result = reduce(lambda x, y: x+y, filter(lambda x: x > 3, map(lambda x: x+1, my_input)))"
      ],
      "execution_count": 150,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "NHWhqj5Xv-7b",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "cdd29eda-c7df-4200-80f7-05017043d500"
      },
      "source": [
        "print(result)"
      ],
      "execution_count": 151,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "29\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vKeiMZ1Dv-7b"
      },
      "source": [
        "### Decorators"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "ZmefSJ0dv-7b"
      },
      "source": [
        "def my_decorator(func):\n",
        "    def my_decorator_impl(x):\n",
        "        result = x if x > 0 else 0\n",
        "        return func(result)\n",
        "    return my_decorator_impl\n",
        "\n",
        "@my_decorator\n",
        "def myfunc(x):\n",
        "    return np.sqrt(x)"
      ],
      "execution_count": 155,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "i87VtGuZLFmZ",
        "outputId": "44456245-52ff-47f6-8809-155732c72aa8"
      },
      "source": [
        "# This is the same\n",
        "new_func = my_decorator(myfunc)\n"
      ],
      "execution_count": 159,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.0"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 159
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "Ro4FAnl6v-7c",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "0a240ac6-34dc-4e66-b88c-6a26b2e35e3a"
      },
      "source": [
        "myfunc(-1)"
      ],
      "execution_count": 156,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "0.0"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 156
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "hQiB8634v-7c"
      },
      "source": [
        "from functools import partial\n",
        "def decor_impl(fun, argument):\n",
        "    def impl(x):\n",
        "        result = x if x > argument else argument\n",
        "        return fun(result)\n",
        "    return impl\n",
        "\n",
        "decor = partial(decor_impl, argument = 2)\n",
        "\n",
        "@decor\n",
        "def myfunc(x):\n",
        "    return np.sqrt(x)"
      ],
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "3DZeQkflv-7c",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "outputId": "0c759875-29ea-4ca4-9c7d-1d262495d2a7"
      },
      "source": [
        "myfunc(-1)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "1.4142135623730951"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 98
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "DWD6ppucv-7c"
      },
      "source": [
        "def para(dec):\n",
        "    def layer(*args, **kwargs):\n",
        "        def repl(f):\n",
        "            return dec(f, *args, **kwargs)\n",
        "        return repl\n",
        "    return layer\n",
        "\n",
        "@para\n",
        "def decor(f, n):\n",
        "    def impl(x):\n",
        "        result = x if x > n else n\n",
        "        return f(result)\n",
        "    return impl\n",
        "\n",
        "@decor(0)\n",
        "def myfunc(x):\n",
        "    return np.sqrt(x)"
      ],
      "execution_count": 160,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "erOdedLUNPHt"
      },
      "source": [
        "def para(dec):\n",
        "    def layer(*args, **kwargs):\n",
        "        def repl(f):\n",
        "            return dec(f, *args, **kwargs)\n",
        "        return repl\n",
        "    return layer\n",
        "\n",
        "def decor(f, n):\n",
        "    def impl(x):\n",
        "        result = x if x > n else n\n",
        "        return f(result)\n",
        "    return impl"
      ],
      "execution_count": 161,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "pycharm": {
          "name": "#%%\n"
        },
        "id": "MQmxUwDbv-7c"
      },
      "source": [
        ""
      ],
      "execution_count": 162,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "p8gBy3ROFgrC"
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}